local ActivityExcel = require("excel.Activity")
local WildBossConfig = ActivityExcel.wildboss
local Map = require("core.Map")
local InnerDataManagerFW = require("innerdata.InnerDataManagerFW")
local InnerDataDefine = require("innerdata.Define")
local ActDefine = require("activity.Define")
--local Util = require("common.Util")
local Lang = require("common.Lang")
local Broadcast = require("broadcast.Broadcast")
local LuaMongo = _G.lua_mongo
local DB = require("common.DB")
local ActHandlerW = require("activity.HandlerW")
local ExcelMonster = require("excel.Monster")
local MapExcel = require("excel.Map")
local Timer = require("core.Timer")
local Grid = require("bag.Grid")
local MailLogicFW = require("mail.MailLogicFW")
local ItemDefine = require("bag.ItemDefine")
local MonsterAttrW = require("monster.MonsterAttrW")

WildBossList = WildBossList or {}

--CallBackList = CallBackList or {}

---------------------------------
--每个活动的数据在DB中是以活动配置编号作为键进行保存的
---------------------------------

function onActCheck()
    if WildBossList._configList then
        for nActNum, nActArgs in pairs(WildBossList._configList) do
            local nActConfigData = WildBossConfig[nActNum]
            if nActConfigData and nActConfigData.isopen == 0 then
                --检查有没有要开放的活动
                local nLeftTime = os.time() - nActArgs.lastHitTime
                if not onCheckActIsBeginBefore(nActNum) and not onCheckActIsRunning(nActNum) then
                    if nActArgs.lastHitTime ~= 0 and nLeftTime < nActConfigData.timesplit and nActConfigData.timesplit - nLeftTime <= 300 then
                        onProcessAct(nActNum, ActDefine.ACT_STATE_BEFORESTART, nActArgs)
                    end
                end

                if not onCheckActIsRunning(nActNum) then
                    if nActArgs.lastHitTime == 0 or (os.time() - nActArgs.lastHitTime >= nActConfigData.timesplit) then
                        if not onProcessAct(nActNum, ActDefine.ACT_STATE_RUNNING, nActArgs) then

                        end
                    end
                end
            end
        end
    end
end

function onProcessAct(actNum, actState, actArgs)
    if not actNum or not actState then
        return false
    end

    local nActConfigData = WildBossConfig[actNum]
    if actState == ActDefine.ACT_STATE_BEFORESTART then
        if not onCheckActIsBeginBefore(actNum) and not onCheckActIsRunning(actNum) then
            WildBossList._beginbefore[actNum] = {actnum = actNum, actArgs = actArgs, starttime = os.time(), endtime = os.time() + (nActConfigData.timesplit - (os.time() - actArgs.lastHitTime))}
            onSend2LActUpdate(actState, actArgs)
            ActHandlerW.onSend2ClientWildBossActUpdate(actNum, 2, actArgs)
            return true
        end
    elseif actState == ActDefine.ACT_STATE_RUNNING then
        if not onCheckActIsRunning(actNum) then
            WildBossList._beginbefore[actNum] = nil
            WildBossList._running[actNum] = {actnum = actNum, actArgs = actArgs}
            onRunning(actNum, actArgs)
            onSend2LActUpdate(actState, actArgs)
            --ActHandlerW.onSendBroadcast(actType, actState)
            ActHandlerW.onSend2ClientWildBossActUpdate(actNum, 2, actArgs)
            return true
        end
    elseif actState == ActDefine.ACT_STATE_ENDED then
        if not WildBossList._endList[actNum] then
            WildBossList._endList[actNum] = {}
        end
        WildBossList._beginbefore[actNum] = nil
        WildBossList._running[actNum] = nil
        WildBossList._endList[actNum] = 1
        onEnd(actNum, actArgs)
        onSend2LActUpdate(actState, actArgs)
        ActHandlerW.onSend2ClientWildBossActUpdate(actNum, 2, actArgs)
        --ActHandlerW.onSendBroadcast(actType, actState)
        return true
    end
    return false
end


function onGetActStatus(actNum, actArgs)
    --Util.printTable(WildBossList)
    local nActConfigData = WildBossConfig[actNum]
    if not nActConfigData then
        return
    end

    if WildBossList._beginbefore and WildBossList._beginbefore[actNum] then
        return ActDefine.ACT_STATE_BEFORESTART
    elseif WildBossList._running and WildBossList._running[actNum] then
        return ActDefine.ACT_STATE_RUNNING
    else
        if actArgs.lastHitTime > 0 and (os.time() - WildBossList._configList[actNum].lastHitTime < nActConfigData.timesplit) then
            return ActDefine.ACT_STATE_ENDED
        else
            return ActDefine.ACT_STATE_READY
        end
    end
end

function onCheckIsEnd(startHour, nowHour, startMin, nowMin)
    if startHour == nowHour then
        return startMin <= nowMin
    else
        return startHour < nowHour
    end
end

function onGetLeftTime(actNum, actArgs)
    local nActConfigID = actArgs._configID
    local nActConfigData = WildBossConfig[nActConfigID]
    if nActConfigData then
        local nStatus = onGetActStatus(nActConfigID, actArgs)
        if nStatus == ActDefine.ACT_STATE_ENDED then
            return nActConfigData.timesplit - (os.time() - WildBossList._configList[actNum].lastHitTime)
        elseif nStatus == ActDefine.ACT_STATE_BEFORESTART then
            local nLeft = WildBossList._beginbefore[actNum].endtime - os.time()
            return nLeft
        elseif nStatus == ActDefine.ACT_STATE_RUNNING then
            return 0
        else
            return 0
        end
    end
end

function onGetActArgs(actNum)
    return WildBossConfig[actNum].args
end

function onGetActArgsValue(actNum, actArgsType)
    local nArgs = WildBossConfig[actNum].args
    if nArgs then
        return nArgs[actArgsType]
    end
end

function onGetActCondition(actNum)
    return WildBossConfig[actNum].condition
end

function onCheckActIsBeginBefore(actNum)
    if WildBossList._beginbefore[actNum] then
        return true
    end
    return false
end

function onCheckActIsRunning(actNum)
    if WildBossList._running[actNum] then
        return true
    end
end

--function onDayCrossActUpdate()
--    for k, v in pairs(WildBossConfig) do
--        if v._endList then
--            v._endList = {}
--        end
--    end
--end

function onSend2LActUpdate(status, actArgs)
    local nSend2Ldata = {
        type = 1,
        data = {
            status = status,
            actType = ActDefine.ACT_TYPE_WILDBOSS,
            actArgs = actArgs,
        }
    }
    InnerDataManagerFW.Send2LInnerData(nil, InnerDataDefine.INNERDATA_TYPE_ACT, nSend2Ldata)
end

--function onRegisterCallBack(nActType, onBeginBefore, onRunning, onEnd, actArgs)
--    CallBackList[nActType] = {[ActDefine.ACT_STATE_BEFORESTART] = onBeginBefore, [ActDefine.ACT_STATE_RUNNING] = onRunning, [ActDefine.ACT_STATE_ENDED] = onEnd, args = actArgs}
--end

--function onAddAct(actConfigID, startHour, startMin, ruleID, status)
--    local nActConfigData = WildBossConfig[actConfigID]
--    if not nActConfigData then
--        return
--    end
--
--    local nDifTime = math.ceil(Timer.onGetDeviationTime("activitycheck", true) / 1000) --修正秒数误差
--
--    local nStatus = tonumber(status)
--
--    local nTempNum = actConfigID..startHour..startMin
--    local nActArgs = {_configID = actConfigID, hour = tonumber(startHour), min = tonumber(startMin), ruleid = tonumber(ruleID), type = nActConfigData.actType}
--    onProcessAct(nActConfigData.actType, actConfigID, nTempNum, 0, ActDefine.ACT_STATE_READY, nActArgs)
--
--    if onCheckActIsBeginBefore(nActConfigData.actType) or onCheckActIsRunning(nActConfigData.actType) then
--        return
--    end
--
--    if nStatus == 1 then         --添加到预告列表
--        onProcessAct(nActConfigData.actType, actConfigID, nTempNum, nActRule.beginbefore * 60 - nDifTime, ActDefine.ACT_STATE_BEFORESTART, nActArgs)
--    elseif nStatus == 2 then     --添加到进行中列表
--        onProcessAct(nActConfigData.actType, actConfigID, nTempNum, nActRule.gap * 60 - nDifTime, ActDefine.ACT_STATE_RUNNING, nActArgs)
--    end
--    Util.printTable(WildBossList)
--end
--
--
--function onEndAct(actConfigID)
--    local nActConfigData = WildBossConfig[actConfigID]
--    if not nActConfigData then
--        return
--    end
--
--    local nActType = nActConfigData.actType
--    if WildBossList[nActType] and (WildBossList[nActType]._beginbefore or WildBossList[nActType]._running) then
--        local nActArgs = WildBossList[nActType]._beginbefore and WildBossList[nActType]._beginbefore.actArgs or WildBossList[nActType]._running.actArgs
--        local nTempNum = actConfigID .. nActArgs.hour..nActArgs.min
--        onProcessAct(nActType, actConfigID, nTempNum, 0, ActDefine.ACT_STATE_ENDED, nActArgs)
--    end
--end


--function onBeginBefore(actNum, actArgs)
--    print("has beginbefore")
--end

function onRunning(actNum, actArgs)
    print("wild boss has running")
    local nActConfigID = actArgs._configID
    local nActConfigData = WildBossConfig[nActConfigID]
    if nActConfigData then
        local nArgData = nActConfigData.args
        local nMapID = nArgData[ActDefine.ACT_ARGS_MAPID]
        local nMonsterPosX = nArgData[ActDefine.ACT_ARGS_MONSTER_POSX]
        local nMonsterPosY = nArgData[ActDefine.ACT_ARGS_MONSTER_POSY]
        local nMonsterID = nArgData[ActDefine.ACT_ARGS_MONSTERID]

        --local noKillDay = 0
        --local nBossLv = 0

        --local lvDownData = ExcelMonster.monster[nMonsterID].dynamic_lvdown

        --local nDyMonsterData = MonsterAttrW.getDyMonsterData(nMonsterID)
        --if nDyMonsterData then
        --    --这里加3600 一小时是为了避免误差的问题，增加几分钟也可
        --    local noKillDay = math.floor(nDyMonsterData.lastKillTime and math.abs((os.time() - ((nDyMonsterData.lastKillTime or 0) + 3600))) / 86400)
        --    local noKillDayLv = math.floor(noKillDay / lvDownData)
        --    local nSrcLv = nDyMonsterData.lv or 0
        --    nBossLv = nSrcLv

        --    nDecLv = (nSrcLv - noKillDayLv) < 0 and 0 or (nSrcLv - noKillDayLv)
        --    if nDecLv ~= nSrcLv then
        --        nDyMonsterData.killCount = 0
        --        nDyMonsterData.lastKillTime = os.time()
        --        nDyMonsterData.lv = nDecLv 
        --        nBossLv = nDecLv
        --        MonsterAttrW.update(nDyMonsterData)
        --    end
        --end

        local nSend2Ldata = {
            type = 1,
            data = {
                monsterID = nMonsterID,
                posX = nMonsterPosX,
                posY = nMonsterPosY,
                mapID = nMapID,
                configID = actArgs._configID,
                --lv = nBossLv,
            }
        }

        InnerDataManagerFW.Send2LInnerData(nil, InnerDataDefine.INNERDATA_TYPE_WILDBOSS, nSend2Ldata)
        local nMonsterName = ExcelMonster.monster[nMonsterID].name
        local nMapName = MapExcel.scene[nMapID].name
        local nStr = string.format(Lang.DAILY_ACTIVITY_WILDBOSS_OPEN, nMonsterName, nMapName, actNum, nMapID, nMonsterPosX, nMonsterPosY)
        Broadcast.sendBroadcast2World(Lang.GROSSIP + Lang.UP, nStr)
    end
end

function onEnd(actNum, actArgs)
    print("wild boss has end")
    local nActConfigID = actArgs._configID
    local nActConfigData = WildBossConfig[nActConfigID]
    if nActConfigData then

        local nArgData = nActConfigData.args
        local nMapID = nArgData[ActDefine.ACT_ARGS_MAPID]

        local nSend2Ldata = {
            type = 2,
            data = {
                mapID = nMapID,
            }
        }

        local logicID = Map.get_logic_id(nMapID)
        InnerDataManagerFW.Send2LInnerData(nil, InnerDataDefine.INNERDATA_TYPE_WILDBOSS, nSend2Ldata, logicID)
    end
end

local function get_grid(itemID, itemNum, itemColor, itemBind)
    local grid = Grid.create(nil, itemID, itemNum, itemBind, ItemDefine.qualityOut[itemColor])
    return grid
end

function onBossDie(data)
    local actArgs = data.actArgs

    if not actArgs then
        return
    end

    local nConfigData = WildBossConfig[actArgs._configID]
    if nConfigData then

    end

    local nLastHit = data.lastHit
    if nLastHit then
        local nRewardData = nil
        local nRewardList = {}
        if nConfigData.item[4] then
            nRewardData = nConfigData.item[4][1]
            if nRewardData then
                nRewardList[#nRewardList + 1] = get_grid(nRewardData[1], nRewardData[2], nRewardData[3], nRewardData[4] or 0)
            end
            MailLogicFW.addSystemMessage(nLastHit[2], "野外BOSS最后击杀奖励", "亲,恭喜您在野外BOSS挑战中造成致命性一击", nRewardList)
        end

        --Broadcast.sendBroadcast2World(Lang.GROSSIP + Lang.UP, Lang.DAILY_ACTIVITY_WORLDBOSS_LASTHIT)
        local nArgData = WildBossConfig[actArgs._configID].args
        local nMonsterID = nArgData[ActDefine.ACT_ARGS_MONSTERID]
        saveDB(actArgs._configID, nLastHit, nMonsterID)
        local nActArgs = WildBossList._configList[actArgs._configID]
        onProcessAct(actArgs._configID, ActDefine.ACT_STATE_ENDED, nActArgs)
        local nMonsterName = ExcelMonster.monster[nMonsterID].name
        local nStr = string.format(Lang.DAILY_ACTIVITY_WILDBOSS_LASTHIT, nLastHit[1], nMonsterName)
        Broadcast.sendBroadcast2World(Lang.GROSSIP + Lang.UP, nStr)
    end
end

function saveDB(actNum, lastHit, monsterID)
    --local nDyMonsterData = MonsterAttrW.getDyMonsterData(monsterID) or {lv = 0, killCount = 0, lastKillTime = 0, monsterID = monsterID}
    --if lastHit and lastHit[1] then
    --    nDyMonsterData.killCount = nDyMonsterData.killCount and nDyMonsterData.killCount + 1 or 0
    --    nDyMonsterData.lastKillTime = os.time()
    --    nDyMonsterData.lv = nDyMonsterData.lv or 0
    --    local lvUpData = ExcelMonster.monster[monsterID].dynamic_lvup

    --    local nAddLv = math.floor(nDyMonsterData.killCount / lvUpData[1]) >= 1 and 1 or 0
    --    if nAddLv >= 1 then
    --        nDyMonsterData.killCount = 0 
    --    end
    --    nDyMonsterData.lv = (nDyMonsterData.lv + nAddLv) > lvUpData[2] and lvUpData[2] or (nDyMonsterData.lv + nAddLv)
    --else
    --    nDyMonsterData.lv = nDyMonsterData.lv
    --    nDyMonsterData.killCount = nDyMonsterData.killCount
    --end

    WildBossList._configList[actNum].lastHitTime = os.time()
    WildBossList._configList[actNum].lastHitName = lastHit[1]
    WildBossList._configList[actNum].lastHitUuid = lastHit[2]
    LuaMongo.update(DB.db_wildboss, {actConfigID = actNum}, {actConfigID = actNum, lastHitUuid = lastHit[2], lastHitName = lastHit[1], lastHitTime = WildBossList._configList[actNum].lastHitTime}, true)
    --MonsterAttrW.update(nDyMonsterData)
end
function onGetLastHitUser(actNum)
    --LuaMongo.find(DB.db_wildboss, {actConfigID = actNum})
    --local nLastHitData = nil
    --local nReader = {}
    --if not LuaMongo.next(nReader) then
    --    return
    --end
    --nLastHitData = {}
    --nLastHitData.lastHitUuid = nReader.lastHitUuid
    --nLastHitData.lastHitName = nReader.lastHitName
    --return nLastHitData

    if WildBossList._configList[actNum] then
        nLastHitData = {}
        nLastHitData.lastHitUuid = WildBossList._configList[actNum].lastHitUuid
        nLastHitData.lastHitName = WildBossList._configList[actNum].lastHitName
        return nLastHitData
    end
end

function onFlushWildBoss(human, time)
    local nDifTime = math.ceil(Timer.onGetDeviationTime("activitycheck", true) / 1000) --修正秒数误差
    for nActNum, nActArgs in pairs(WildBossList._configList) do
        local nActConfigData = WildBossConfig[nActNum]
        if nActConfigData and nActConfigData.isopen == 0 then
            if not onCheckActIsBeginBefore(nActNum) and not onCheckActIsRunning(nActNum) then
                nActArgs.lastHitTime = os.time() - nActConfigData.timesplit + (60 - nDifTime) + (time or 0)
            end
        end
    end
    onActCheck()
    ActHandlerW.CG_ACTIVITY_DAILYACT_LIST(human, {type = 2})
end

initStatus = initStatus or false
function onInit(clear)

    if initStatus == false or clear then
        if clear then
            for nType, v in pairs(WildBossList) do
                for nActConfigID, nActData in pairs(v._configList) do
                    for nActNum, nActArgs in pairs(nActData) do
                        onProcessAct(nType, nActConfigID, nActNum, 0, ActDefine.ACT_STATE_ENDED, nActArgs)
                    end
                end
                WildBossList = nil
            end
        end

        WildBossList = {
            _beginbefore = WildBossList._beginbefore or {},
            _running = WildBossList._running or {},                 --运行中的活动
            _endList = {},
            _configList = WildBossList._configList or {}
        }

        for k, v in pairs(WildBossConfig) do
            local actNum = k
            if not WildBossList._configList[k] then
                WildBossList._configList[k] = {}
            end

            LuaMongo.find(DB.db_wildboss, {actConfigID = k})
            local nReader = {}
            if not LuaMongo.next(nReader) then
                WildBossList._configList[actNum] = {_configID = k, type = v.actType, lastHitTime = 0}
            else
                WildBossList._configList[actNum] = {_configID = k, type = v.actType, lastHitTime = nReader.lastHitTime, lastHitUuid = nReader.lastHitUuid, lastHitName = nReader.lastHitName}
            end


        end
        initStatus = true
    end
end

onInit()

